package org.sample.project.custom;

import liquibase.Scope;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.changelog.visitor.ChangeExecListener;
import liquibase.database.Database;
import liquibase.exception.*;
import liquibase.executor.ExecutorService;
import liquibase.precondition.AbstractPrecondition;
import liquibase.snapshot.InvalidExampleException;
import liquibase.snapshot.SnapshotGeneratorFactory;
import liquibase.statement.core.RawParameterizedSqlStatement;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Table;
import org.sample.project.service.DbObjectCheckFactory;

/**
 * 自定义预条件
 * Created by foolrabbit on 2025-01-24.
 */
public class MyTableNotExistsCheckPrecondition extends AbstractPrecondition {
    // 定义参数
    private String catalogName;
    private String schemaName;
    private String tableName;

    @Override
    public String getName() {
        return "myTableNotExistsCheck"; // 预条件的名称，用于在变更集中引用
    }

    @Override
    public Warnings warn(Database database) {
        return new Warnings();
    }

    @Override
    public ValidationErrors validate(Database database) {
        return new ValidationErrors();
    }

    @Override
    public void check(Database database, DatabaseChangeLog changeLog, ChangeSet changeSet, ChangeExecListener changeExecListener) throws PreconditionFailedException, PreconditionErrorException {
        try {
            String correctedTableName = database.correctObjectName(this.getTableName(), Table.class);
            if (SnapshotGeneratorFactory.getInstance().has((new Table()).setName(correctedTableName).setSchema(new Schema(this.getCatalogName(), this.getSchemaName())), database)) {
                throw new PreconditionFailedException("Table " + database.escapeTableName(this.getCatalogName(), this.getSchemaName(), this.getTableName()) + " exist", changeLog, this);
            }
            // 根据数据库类型生成 SQL 查询
            /*String sql = getSqlForDatabase(database);
            Object oResult = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database).queryForObject(new RawParameterizedSqlStatement(sql), String.class);
            if (oResult == null) {
                throw new PreconditionFailedException("No rows returned from SQL Precondition", changeLog, this);
            } else {
                String result = oResult.toString();
                String expectedResult = this.getExpectedResult();
                if (!expectedResult.equals(result)) {
                    throw new PreconditionFailedException("SQL Precondition failed.  Expected '" + expectedResult + "' got '" + result + "'", changeLog, this);
                }
            }*/
        }
        catch (DatabaseException | InvalidExampleException e) {
            throw new PreconditionErrorException(e, changeLog, this);
        }
    }

    private String getSqlForDatabase(Database database) {
        return DbObjectCheckFactory.getObjectCheckService(database.getDatabaseProductName()).tableExists(schemaName, tableName);
    }

    public void setSchemaName(String schemaName) {
        this.schemaName = schemaName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getSchemaName() {
        return schemaName;
    }

    public String getTableName() {
        return tableName;
    }

    public String getCatalogName() {
        return catalogName;
    }

    public void setCatalogName(String catalogName) {
        this.catalogName = catalogName;
    }

    @Override
    public String getSerializedObjectNamespace() {
        return "http://www.liquibase.org/xml/ns/dbchangelog";
    }
}